import React, { useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { MODULE_TYPES, TOOLBAR_BUTTON_TYPES } from '@ohif/core';
import { ToolbarButton, ContextMenu } from '@ohif/ui';
import { commandsManager, extensionManager } from './../../App.js';
import { useAppContext } from './../../context/AppContext';
import { useTranslation } from 'react-i18next';
import { Image } from 'antd';
import classnames from 'classnames';

import './Toolbar.styl';

function _isActiveButton(d, props) {
  if (d.type === TOOLBAR_BUTTON_TYPES.STATE) {
    const { keys, values } = d.options || {};
    if (keys && keys.length > 0) {
      let denied = false;
      keys.forEach((key, idx) => {
        let val = props;
        let subKeys = key.split('.');
        let isArray = false;
        subKeys.forEach(k => {
          if (val === undefined) {
            denied = true;
            return;
          }

          if (k === 'Array') {
            isArray = true;
          } else {
            if (isArray) {
              val = val[props[subKeys[0]][k]];
              isArray = false;
            } else {
              val = val[k];
            }
          }
        });
        denied = denied || val !== values[idx];
      });
      return !denied;
    }
  }

  return false;
}

function _getDefaultTool(isMobile) {
  return isMobile ? {
    id: 'StackScroll',
    label: 'Stack Scroll',
    icon: 'stack',
    type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
    commandName: 'setToolActive',
    commandOptions: { toolName: 'StackScroll' },
  } : {
    id: 'Select',
    label: 'Select',
    icon: 'pointer',
    className: 'hideOnPhone',
    type: TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE,
    commandName: 'setToolActive',
    commandOptions: { toolName: 'Select' },
  }
}

const Toolbar = () => {
  const { appConfig, activeContexts } = useAppContext();
  const { t } = useTranslation("Modal");

  const defaultButton = useMemo(() => {
    return _getDefaultTool(appConfig.isMobile);
  }, [appConfig.isMobile]);

  const [activeButtons, setActiveButtons] = useState([defaultButton]);

  const stateProps = useSelector(state => {
    return {
      viewports: state.viewports[state.viewports.viewMode],
      preferences: state.preferences,
    };
  });

  const toolbarButtons = useMemo(() => {
    const toolbarModules = extensionManager.modules[MODULE_TYPES.TOOLBAR];
    const leftButtonDefinitions = [], rightButtonDefinitions = [];
    const stateButtons = [];

    toolbarModules.forEach(extension => {
      const { definitions, defaultContext } = extension.module;
      definitions.forEach(d => {
        const context = d.context || defaultContext;

        if (activeContexts.includes(context)) {
          if (extension.extensionId === 'system-settings') {
            rightButtonDefinitions.push(d);
          } else {
            leftButtonDefinitions.push(d);
          }

          if (_isActiveButton(d, stateProps)) {
            stateButtons.push(d);
          }
          if (d.buttons && d.buttons.length > 0) {
            d.buttons.forEach(b => { if (_isActiveButton(b, stateProps)) stateButtons.push(b); });
          }
        }
      });
    });

    return { leftButtonDefinitions, rightButtonDefinitions, stateButtons };
  }, [activeContexts, stateProps]);

  const getButtonComponents = (toolbarButtons, activeButtons) => {
    return toolbarButtons.map(button => button.CustomComponent ?
      getCustomButtonComponent(button, activeButtons) :
      getDefaultButtonComponent(button, activeButtons));
  };

  const getCustomButtonComponent = (button, activeButtons) => {
    const CustomComponent = button.CustomComponent;
    const isValidComponent = typeof CustomComponent === 'function';

    // Check if its a valid customComponent. Later on an CustomToolbarComponent interface could be implemented.
    if (isValidComponent) {
      const activeButtonsIds = activeButtons.map(button => button.id);
      const isActive = activeButtonsIds.includes(button.id);
      const isVisible = activeButtons.reduce(
        (visible, button) =>
          visible || (button.options && button.options.showSlabThickness),
        false
      );

      return (
        <CustomComponent
          toolbarClickCallback={handleToolbarButtonClick}
          button={button}
          key={button.id}
          activeButtons={activeButtonsIds}
          isActive={isActive}
          isVisible={isVisible}
        />
      );
    }
  };

  const getDefaultButtonComponent = (button, activeButtons) => {
    const activeButtonsIds = activeButtons.map(button => button.id);
    const isActive = activeButtonsIds.includes(button.id);
    return (
      <ToolbarButton
        {...button}
        key={button.id}
        onClick={handleToolbarButtonClick.bind(null, button)}
        activeButtons={activeButtonsIds}
        isActive={isActive}
      />
    );
  };

  const handleToolbarButtonClick = (button, evt, props) => {
    const toolbarContext = { appConfig, t };

    let btn = button;

    if (evt && evt.source === 'menu') {
      const key = evt.key;
      if (button.buttons && button.buttons.length > 0 && key) {
        btn = button.buttons.find(b => b.id === key);
      }
    }

    if (btn) {
      const options = Object.assign({ evt }, btn.commandOptions, toolbarContext);
      commandsManager.runCommand(btn.commandName, options);
    } else return;

    // TODO: Use Types ENUM
    // TODO: We can update this to be a `getter` on the extension to query
    //       For the active tools after we apply our updates?
    if (btn.type === TOOLBAR_BUTTON_TYPES.SET_TOOL_ACTIVE) {
      setActiveButtons([btn]);
    } else if (button.type === TOOLBAR_BUTTON_TYPES.BUILD_IN) {
      handleBuiltIn(button);
    } else if (btn.type === TOOLBAR_BUTTON_TYPES.COMMAND && btn.id === 'ResetViewport') {
      setActiveButtons([defaultButton]);
    }
  };

  const handleBuiltIn = (button) => {
    const { id, options } = button;
  };

  const { leftButtonDefinitions, rightButtonDefinitions, stateButtons } = toolbarButtons;
  const leftButtons = useMemo(() => getButtonComponents(
    leftButtonDefinitions,
    activeButtons.concat(stateButtons)
  ), [leftButtonDefinitions, activeButtons, stateButtons]);
  const rightButtons = useMemo(() => getButtonComponents(
    rightButtonDefinitions,
    activeButtons.concat(stateButtons)
  ), [rightButtonDefinitions, activeButtons, stateButtons]);

  return (
    <div className='toolbar'>
      {/* <div className={classnames('brand-logo', 'hideOnPhone')}>
        <Image width={100} src={`${appConfig.routerBasename}/assets/logo.png`} />
      </div> */}
      <div className='toolbar-buttons'>
        <div className='buttons-left'>
          {leftButtons}
        </div>
        <div className='buttons-right'>
          {rightButtons}
        </div>
      </div>
      <ContextMenu onItemClick={handleToolbarButtonClick} extensionManager={extensionManager} />
    </div>
  );
}

export default Toolbar;
